package main

import (
	"archive/zip"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
	"time"
)

func main() {
	// app的用户数据目录
	appUserData := os.Args[1]
	// app 程序下的 Resources 目录
	appResourcesPath := os.Args[2]
	// app 程序的启动文件
	appExe := os.Args[3]
	// 延迟500 毫秒执行
	time.Sleep(500 * time.Millisecond)
	fmt.Println("appUserData:", appUserData)
	fmt.Println("appResourcesPath:", appResourcesPath)
	fmt.Println("appExe:", appExe)
	appdir := appResourcesPath + "/app"
	newAppZip := appUserData + "/lastVersion/app.zip"
	// 删除 程序下的app 文件夹
	os.RemoveAll(appdir)
	UnZip(appResourcesPath, newAppZip)
	os.Remove(newAppZip)
	ctx, cancel := context.WithCancel(context.Background())

	cmd := exec.CommandContext(ctx, appExe)
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
	cmd.Stdout = os.Stdout
	cmd.Start()

	time.Sleep(5 * time.Second)
	fmt.Println("退出程序中...", cmd.Process.Pid)
	cancel()
	cmd.Wait()
}
func UnZip(dst, src string) (err error) {
	// 打开压缩文件，这个 zip 包有个方便的 ReadCloser 类型
	// 这个里面有个方便的 OpenReader 函数，可以比 tar 的时候省去一个打开文件的步骤
	zr, err := zip.OpenReader(src)
	defer zr.Close()
	if err != nil {
		return
	}

	// 如果解压后不是放在当前目录就按照保存目录去创建目录
	if dst != "" {
		if err := os.MkdirAll(dst, 0755); err != nil {
			return err
		}
	}

	// 遍历 zr ，将文件写入到磁盘
	for _, file := range zr.File {
		path := filepath.Join(dst, file.Name)

		// 如果是目录，就创建目录
		if file.FileInfo().IsDir() {
			if err := os.MkdirAll(path, file.Mode()); err != nil {
				return err
			}
			// 因为是目录，跳过当前循环，因为后面都是文件的处理
			continue
		}

		// 获取到 Reader
		fr, err := file.Open()
		if err != nil {
			return err
		}

		// 创建要写出的文件对应的 Write
		fw, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, file.Mode())
		if err != nil {
			return err
		}
		//n
		_, err = io.Copy(fw, fr)
		if err != nil {
			return err
		}

		// 将解压的结果输出
		//fmt.Printf("成功解压 %s ，共写入了 %d 个字符的数据\n", path, n)

		// 因为是在循环中，无法使用 defer ，直接放在最后
		// 不过这样也有问题，当出现 err 的时候就不会执行这个了，
		// 可以把它单独放在一个函数中，这里是个实验，就这样了
		fw.Close()
		fr.Close()
	}
	return nil
}
